/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.account.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.gruul.account.api.constant.AccountQueueNameConstant;
import com.medusa.gruul.account.api.entity.*;
import com.medusa.gruul.account.constant.MemberStatus;
import com.medusa.gruul.account.mapper.*;
import com.medusa.gruul.account.model.dto.UpdateApiMemberExpireTimeDto;
import com.medusa.gruul.account.model.dto.UpdateApiMemberExpireTimePageDto;
import com.medusa.gruul.account.model.dto.UpgradeApiMemberRankDto;
import com.medusa.gruul.account.model.dto.UpgradeApiMemberRankPageDto;
import com.medusa.gruul.account.model.vo.*;
import com.medusa.gruul.account.service.IApiMemberInfoService;
import com.medusa.gruul.account.service.IMemberCardInfoService;
import com.medusa.gruul.account.service.IMemberSwitchService;
import com.medusa.gruul.account.service.IMiniAccountExtendsService;
import com.medusa.gruul.common.core.auth.client.helper.ISecurity;
import com.medusa.gruul.common.core.constant.CommonConstants;
import com.medusa.gruul.common.core.exception.ServiceException;
import com.medusa.gruul.common.core.util.CurUserUtil;
import com.medusa.gruul.common.core.util.IPUtils;
import com.medusa.gruul.common.core.util.Result;
import com.medusa.gruul.common.core.util.SystemCode;
import com.medusa.gruul.common.data.tenant.ShopContextHolder;
import com.medusa.gruul.common.data.tenant.TenantContextHolder;
import com.medusa.gruul.common.dto.CurUserDto;
import com.medusa.gruul.goods.api.entity.RebateSet;
import com.medusa.gruul.goods.api.feign.RemoteGoodsService;
import com.medusa.gruul.integral.api.feign.RemoteIntegralService;
import com.medusa.gruul.payment.api.feign.RemotePaymentService;
import com.medusa.gruul.payment.api.model.pay.PayParam;
import com.medusa.gruul.payment.api.model.dto.PayRequestDto;
import com.medusa.gruul.payment.api.model.dto.PayResultDto;
import com.medusa.gruul.payment.api.model.pay.PayResult;
import com.medusa.gruul.platform.api.feign.RemoteMiniInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 会员信息实现类 小程序端
 * @Author: zhaokw29701
 * @Date: 2020/5/30 22:31
 **/
@Service
public class ApiMemberInfoServiceImpl extends ServiceImpl<MemberInfoMapper, MemberInfo> implements IApiMemberInfoService {

    @Autowired
    private MemberInfoMapper memberInfoMapper;

    @Autowired
    private MiniAccountMapper miniAccountMapper;

    @Autowired
    private MemberCardInfoMapper memberCardInfoMapper;
    @Autowired
    private IMemberCardInfoService memberCardInfoService;
    @Autowired
    private MemberCardPrivilegeMapper memberCardPrivilegeMapper;

    @Autowired
    private MemberCardPrivilegeGroupMapper memberCardPrivilegeGroupMapper;

    @Autowired
    private RemotePaymentService remotePaymentService;

    @Autowired
    private RemoteIntegralService remoteIntegralService;

    @Autowired
    private RemoteMiniInfoService remoteMiniInfoService;

    @Autowired
    private IMiniAccountExtendsService miniAccountExtendsService;

    @Autowired
    private MemberBalanceRecordMapper memberBalanceRecordMapper;

    @Autowired
    private IMemberSwitchService memberSwitchService;
    @Autowired
    private RemoteGoodsService remoteGoodsService;

    @Override
    public List<ApiMemberCardInfoVo> getMemberInfo() {
        String tenantId = TenantContextHolder.getTenantId();
        String userId = "";
        //获取用户信息
        CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
        if (curUserDto != null && curUserDto.getUserId() != null) {
            userId = curUserDto.getUserId();
        }
        List<ApiMemberCardInfoVo> apiMemberCardInfoVos = new ArrayList<>();
        MemberSwitch memberSwitch = new MemberSwitch();
        memberSwitch.setMemberModel(0)
                .setTenantId(tenantId);
        MemberSwitch memberSwitches =
                memberSwitchService.getByTenantIdAndMemberModelMemberSwitch(tenantId, memberSwitch.getMemberModel());
        if (memberSwitches == null || memberSwitches.getState().equals(CommonConstants.NUMBER_ZERO)) {
            //获取会员信息
            List<MemberInfo> memberInfos = memberInfoMapper.getMemberInfoByUserId(tenantId, userId);
            if (CollectionUtil.isNotEmpty(memberInfos)) {
                //是会员
                for (MemberInfo memberInfo : memberInfos) {
                    ApiMemberCardInfoVo apiMemberCardInfoVo = new ApiMemberCardInfoVo();
                    //PC端关闭会员，当前用户是会员
                    apiMemberCardInfoVo.setStatus(MemberStatus.THREE);
                    apiMemberCardInfoVo.setState(memberInfo.getState())
                            .setId(memberInfo.getId())
                            .setMemberCardInfoId(memberInfo.getMemberCardInfoId())
                            .setMemberExpireTime(memberInfo.getMemberExpireTime());
                    MemberCardInfo memberCardInfoTemp = memberCardInfoMapper.getApiMemberCardInfo(memberInfo.getMemberCardInfoId());
                    apiMemberCardInfoVo.setRankCode(memberCardInfoTemp.getRankCode())
                            .setRankName(memberCardInfoTemp.getRankName());
                    //获取用户信息
                    MiniAccountExtends accountExtends = miniAccountExtendsService.findByShopUserId(userId);
                    apiMemberCardInfoVo.setUserId(userId)
                            .setSupplyBonus(accountExtends.getSupplyBonus())
                            .setRebateBonus(accountExtends.getRebateBonus())
                            .setSupplyAndRebateBonus(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()));
                    apiMemberCardInfoVos.add(apiMemberCardInfoVo);
                }
                apiMemberCardInfoVos = apiMemberCardInfoVos.stream().sorted(Comparator.comparing(ApiMemberCardInfoVo::getRankCode).reversed()).collect(Collectors.toList());
            } else {
                ApiMemberCardInfoVo apiMemberCardInfoVo = new ApiMemberCardInfoVo();
                //PC端关闭会员，不是会员
                apiMemberCardInfoVo.setStatus(MemberStatus.FOUR);
                MiniAccountExtends accountExtends = miniAccountExtendsService.findByShopUserId(userId);
                apiMemberCardInfoVo.setUserId(userId)
                        .setSupplyBonus(accountExtends.getSupplyBonus())
                        .setRebateBonus(accountExtends.getRebateBonus())
                        .setSupplyAndRebateBonus(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()))
                        .setState(0);
                apiMemberCardInfoVos.add(apiMemberCardInfoVo);
            }
        } else {
            //获取会员信息
            List<MemberInfo> memberInfos = memberInfoMapper.getMemberInfoByUserId(tenantId, userId);
            //是会员
            if (CollectionUtil.isNotEmpty(memberInfos)) {
                for (MemberInfo memberInfo : memberInfos) {
                    ApiMemberCardInfoVo apiMemberCardInfoVo = new ApiMemberCardInfoVo();
                    apiMemberCardInfoVo
                            .setStatus(CommonConstants.NUMBER_ONE)
                            .setState(memberInfo.getState())
                            .setId(memberInfo.getId())
                            .setMemberCardInfoId(memberInfo.getMemberCardInfoId())
                            .setMemberExpireTime(memberInfo.getMemberExpireTime());
                    MemberCardInfo memberCardInfoTemp = memberCardInfoMapper.getApiMemberCardInfo(memberInfo.getMemberCardInfoId());
                    apiMemberCardInfoVo
                            .setRankCode(memberCardInfoTemp.getRankCode())
                            .setRankName(memberCardInfoTemp.getRankName());
                    //获取用户信息
                    MiniAccountExtends accountExtends = miniAccountExtendsService.findByShopUserId(userId);
                    apiMemberCardInfoVo.setUserId(userId)
                            .setSupplyBonus(accountExtends.getSupplyBonus())
                            .setRebateBonus(accountExtends.getRebateBonus())
                            .setSupplyAndRebateBonus(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()));
                    apiMemberCardInfoVos.add(apiMemberCardInfoVo);
                }
                apiMemberCardInfoVos = apiMemberCardInfoVos.stream().sorted(Comparator.comparing(ApiMemberCardInfoVo::getRankCode).reversed()).collect(Collectors.toList());
            } else {
                ApiMemberCardInfoVo apiMemberCardInfoVo = new ApiMemberCardInfoVo();
                //不是会员
                apiMemberCardInfoVo.setStatus(MemberStatus.TWO);
                MiniAccountExtends accountExtends = miniAccountExtendsService.findByShopUserId(userId);
                apiMemberCardInfoVo.setUserId(userId)
                        .setSupplyBonus(accountExtends.getSupplyBonus())
                        .setRebateBonus(accountExtends.getRebateBonus())
                        .setSupplyAndRebateBonus(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()))
                        .setState(0);
                apiMemberCardInfoVos.add(apiMemberCardInfoVo);
            }
        }
        return apiMemberCardInfoVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayResultDto updateMemberExpireTime(UpdateApiMemberExpireTimeDto updateApiMemberExpireTimeDto) {
        String tenantId = TenantContextHolder.getTenantId();
        DateTime t1 = DateUtil.parseDateTime(updateApiMemberExpireTimeDto.getMemberExpireTime());
        DateTime t2 = DateTime.now();
        if (t1.compareTo(t2) < 0) {
            throw new ServiceException("小程序端会员续费失败，会员卡已到期", SystemCode.DATA_UPDATE_FAILED.getCode());
        }
        //付费购买
        if (updateApiMemberExpireTimeDto.getOpenType().equals(CommonConstants.NUMBER_ONE)) {
            Balance balance = new Balance(updateApiMemberExpireTimeDto, tenantId).invoke();
            if (balance.is()) {
                return balance.getPayResultDto();
            }
        } else if (updateApiMemberExpireTimeDto.getOpenType().equals(CommonConstants.NUMBER_TWO)) {
            integral(updateApiMemberExpireTimeDto);

        } else {

        }
        return new PayResultDto();
    }

    @Override
    public Object updateMemberExpireTimePage(UpdateApiMemberExpireTimePageDto memberExpire) {
        if ( DateUtil.parseDateTime(memberExpire.getMemberExpireTime()).compareTo(DateTime.now())< 0) {
            throw new ServiceException("会员续费失败，会员卡已到期", SystemCode.DATA_UPDATE_FAILED.getCode());
        }
        PayParam payParam = new PayParam()
                .setSubject("会员续费")
                .setBody("会员续费")
                .setPayType(memberExpire.getPayType())
                .setOrderId(memberExpire.getMemberNumber())
                .setRouteKey(AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE)
                .setPrice(memberExpire.getPayAmount())
                .setSeconds(15*60L)
                .setAttach(
                        JSON.toJSONString(
                                new MemberCompletedVo()
                                .setUserRank(ISecurity.user().must().getShopUserId())
                                .setMNumber(memberExpire.getMemberNumber())
                                .setType(2)
                                .setDate(memberExpire.getDate())
                        )
                );
        return remotePaymentService.toPayPage(payParam).successData().getData();
    }

    /**
     * 更新到期时间，积分兑换
     *
     * @param updateApiMemberExpireTimeDto com.medusa.gruul.account.model.dto.UpdateApiMemberExpireTimeDto
     */
    private void integral(UpdateApiMemberExpireTimeDto updateApiMemberExpireTimeDto) {
        CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
        String shopUserId = curUserDto.getUserId();
        BigDecimal useAmount = updateApiMemberExpireTimeDto.getAvailableAmount();
        Result result = remoteIntegralService.conversionClubCard(shopUserId, useAmount);
        if (result.getCode() == CommonConstants.SUCCESS) {
            //会员续费
            //取时间
            Date date = DateUtil.parseDateTime(updateApiMemberExpireTimeDto.getMemberExpireTime());
            Calendar calendar = Calendar.getInstance();
            //需要将date数据转移到Calender对象中操作
            calendar.setTime(date);
            //把日期往后增加n天.正数往后推,负数往前移动
            calendar.add(Calendar.DATE, updateApiMemberExpireTimeDto.getDate().intValue());
            //这个时间就是日期往后推n天的结果
            date = calendar.getTime();
            updateApiMemberExpireTimeDto.setMemberExpireTime(DateUtil.formatDateTime(date));
            int update = memberInfoMapper.updateApiMemberExpireTime(updateApiMemberExpireTimeDto);
            if (update < 1) {
                throw new ServiceException("小程序端会员续费失败", SystemCode.DATA_UPDATE_FAILED.getCode());
            }
        } else {
            throw new ServiceException(result.getMsg(), SystemCode.DATA_UPDATE_FAILED.getCode());
        }
    }

    @Override
    public MemberCardUpgradeVo getMemberCardUpgrade(String memberId) {
        MemberCardUpgradeVo memberCardUpgradeVo = new MemberCardUpgradeVo();
        String tenantId = TenantContextHolder.getTenantId();
        CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
        String userId = "";
        if (curUserDto != null && curUserDto.getUserId() != null) {
            String shopUserId = curUserDto.getUserId();
            userId = miniAccountMapper.getUserInfoByShopUserId(tenantId, shopUserId);
            if (userId != null) {
                MiniAccount miniAccount = miniAccountMapper.getMemberInfo(tenantId, userId);
                MiniAccountExtends accountExtends = miniAccountExtendsService.findByShopUserId(shopUserId);
                //获取返利设置里会员返利金额是否可用,可用：返利+用户余额  不可用：用户余额
                String shopId = ShopContextHolder.getShopId();
                RebateSet rebateSet = remoteGoodsService.getRebateSet(tenantId, shopId);
                List<MemberInfo> memberInfoList = memberInfoMapper.selectList(new QueryWrapper<MemberInfo>().eq("state", 1).eq("tenant_id", tenantId).eq("user_id", shopUserId));
                //是会员
                if (CollectionUtil.isNotEmpty(memberInfoList)) {
                    if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ONE.toString())) {
                        memberCardUpgradeVo.setAccountBalance(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()));
                    } else {
                        memberCardUpgradeVo.setAccountBalance(accountExtends.getSupplyBonus());
                    }
                } else {
                    //不是会员,是普通用户
                    if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ZERO.toString())) {
                        memberCardUpgradeVo.setAccountBalance(accountExtends.getSupplyBonus().add(accountExtends.getRebateBonus()));
                    } else {
                        memberCardUpgradeVo.setAccountBalance(accountExtends.getSupplyBonus());
                    }
                }
                memberCardUpgradeVo.setAvatarUrl(miniAccount.getAvatarUrl())
                        .setNikeName(miniAccount.getNikeName())
                        .setUserId(userId);
                BigDecimal integral = miniAccountMapper.getIntegralByShopUserId(tenantId, curUserDto.getUserId());
                //账户可用积分
                memberCardUpgradeVo.setUseAmount(integral);
                MemberInfo memberInfoTemp = memberInfoMapper.selectById(memberId);
                MemberCardInfo memberCardInfoTemp = memberCardInfoMapper.getApiMemberCardInfo(memberInfoTemp.getMemberCardInfoId());
                ZoneId zoneId = ZoneId.systemDefault();
                ZonedDateTime zdt = memberInfoTemp.getMemberExpireTime().atZone(zoneId);
                Date date = Date.from(zdt.toInstant());
                Date date2 = new Date();
                int day = differentDaysByMillisecond(date2, date);
                if (day < 0) {
                    day = 0;
                }
                memberCardUpgradeVo.setRemainDate(String.valueOf(day))
                        .setRankCode(memberCardInfoTemp.getRankCode())
                        .setRankName(memberCardInfoTemp.getRankName())
                        .setMemberNumber(memberInfoTemp.getMemberNumber());
                List<MemberCardInfoCenterVo> memberCardInfoCenterVos = new ArrayList<>();
                List<MemberCardInfo> memberCardInfoList = memberCardInfoService.getCurrentMemberCardInfo(tenantId);
                for (MemberCardInfo memberCardInfo : memberCardInfoList) {
                    MemberCardInfoCenterVo memberCardInfoCenterVo = getMemberCardInfoCenterVo(memberCardUpgradeVo, tenantId, memberCardInfo);
                    memberCardInfoCenterVos.add(memberCardInfoCenterVo);
                    if (memberCardInfo.getRankCode().equals(memberCardUpgradeVo.getRankCode())) {
                        memberCardUpgradeVo.setOpenValue(memberCardInfo.getOpenValue())
                                .setUseInDate(memberCardInfo.getUseInDate());
                    }
                }
                memberCardUpgradeVo.setMemberCardInfoCenterVos(memberCardInfoCenterVos);
            }
        }
        return memberCardUpgradeVo;
    }

    /**
     * 获取指定会员卡相关信息
     *
     * @param memberCardUpgradeVo com.medusa.gruul.account.model.vo.MemberCardUpgradeVo
     * @param tenantId            租户id
     * @param memberCardInfo      会员卡相关信息
     * @return com.medusa.gruul.account.model.vo.MemberCardInfoCenterVo
     */
    private MemberCardInfoCenterVo getMemberCardInfoCenterVo(MemberCardUpgradeVo memberCardUpgradeVo, String tenantId, MemberCardInfo memberCardInfo) {
        MemberCardInfoCenterVo memberCardInfoCenterVo = new MemberCardInfoCenterVo();
        memberCardInfoCenterVo.setMemberCardInfoId(memberCardInfo.getId());
        memberCardInfoCenterVo.setTitle(memberCardInfo.getTitle())
                .setRankCode(memberCardInfo.getRankCode())
                .setRankName(memberCardInfo.getRankName())
                .setOpenType(memberCardInfo.getOpenType())
                .setOpenValue(memberCardInfo.getOpenValue())
                .setUseInDate(memberCardInfo.getUseInDate())
                .setBackGroundPicUrl(memberCardInfo.getBackGroundPicUrl())
                .setIsOpen(memberCardInfo.getIsOpen());
        //实际支付金额（积分）：要升级套餐价格*剩余时长数/有效天数
        BigDecimal actualOpenValue = memberCardInfoCenterVo.getOpenValue()
                .multiply(new BigDecimal(memberCardUpgradeVo.getRemainDate()))
                .divide(new BigDecimal(memberCardInfoCenterVo.getUseInDate()), 2, BigDecimal.ROUND_HALF_UP)
                .setScale(2, BigDecimal.ROUND_HALF_UP);

        if (memberCardUpgradeVo.getRemainDate().equals("0")){
            actualOpenValue = memberCardInfoCenterVo.getOpenValue();
        }
        memberCardInfoCenterVo.setActualOpenValue(actualOpenValue);
        //获取租户下特权开关为开启状态下的会员卡权益列表
        List<MemberPrivilegeVo> memberPrivilegeVos = memberCardPrivilegeMapper.selectMemberCardPrivilege(tenantId);
        for (MemberPrivilegeVo memberPrivilegeVo : memberPrivilegeVos) {
            MemberCardPrivilegeGroup memberCardPrivilegeGroup = memberCardPrivilegeGroupMapper.selectMemberCardPrivilegeGroup(tenantId, memberCardInfo.getId(), memberPrivilegeVo.getId());
            if (memberCardPrivilegeGroup != null) {
                memberPrivilegeVo.setIsSelected(1);
                memberPrivilegeVo.setValue(memberCardPrivilegeGroup.getValue());
            } else {
                memberPrivilegeVo.setIsSelected(0);
            }
        }

        memberCardInfoCenterVo.setMemberCardPrivileges(memberPrivilegeVos);
        return memberCardInfoCenterVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayResultDto upgradeMemberRank(UpgradeApiMemberRankDto upgradeApiMemberRankDto) {
        String tenantId = TenantContextHolder.getTenantId();
        upgradeApiMemberRankDto.setTenantId(tenantId);
        //付费购买
        if (upgradeApiMemberRankDto.getOpenType().equals(CommonConstants.NUMBER_ONE)) {
            //微信支付
            if (upgradeApiMemberRankDto.getPaymentType().equals(CommonConstants.NUMBER_ONE)) {
                return upgradeApiMemberWechatPay(upgradeApiMemberRankDto, tenantId);

                //余额支付
            } else if (upgradeApiMemberRankDto.getPaymentType().equals(CommonConstants.NUMBER_TWO)) {
                upgradeApiMemberBalancePay(upgradeApiMemberRankDto, tenantId);

            }
            //积分兑换
        } else if (upgradeApiMemberRankDto.getOpenType().equals(CommonConstants.NUMBER_TWO)) {
            CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
            String shopUserId = curUserDto.getUserId();
            BigDecimal useAmount = upgradeApiMemberRankDto.getAvailableAmount();
            Result result = remoteIntegralService.conversionClubCard(shopUserId, useAmount);
            if (result.getCode() == CommonConstants.SUCCESS) {
                //会员升级
                upgradeApiMemberRankDto.setTenantId(tenantId);
                upgradeApiMemberRankDto.setUserId(shopUserId);
                int update = memberInfoMapper.upgradeApiMemberRank(upgradeApiMemberRankDto);
                if (update < CommonConstants.NUMBER_ONE) {
                    throw new ServiceException("小程序端会员升级失败", SystemCode.DATA_UPDATE_FAILED.getCode());
                }
            } else {
                throw new ServiceException(result.getMsg(), SystemCode.DATA_UPDATE_FAILED.getCode());
            }

        }
        return new PayResultDto();

    }

    @Override
    public Object upgradeMemberRankPage(UpgradeApiMemberRankPageDto updateMemberRankPage) {
        PayParam payParam = new PayParam()
                .setSubject("会员升级")
                .setBody("会员升级")
                .setOrderId(updateMemberRankPage.getMemberNumber())
                .setPayType(updateMemberRankPage.getPayType())
                .setPrice(updateMemberRankPage.getPayAmount())
                .setRouteKey(AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE)
                .setSeconds(15*60L)
                .setAttach(
                        JSON.toJSONString(
                                new MemberCompletedVo()
                                .setUserRank(updateMemberRankPage.getRankCode())
                                .setMNumber(updateMemberRankPage.getMemberNumber())
                                .setType(3)
                        )
                );
        return remotePaymentService.toPayPage( payParam ).successData().getData();
    }

    /**
     * 微信支付
     *
     * @param upgradeApiMemberRankDto com.medusa.gruul.account.model.dto.UpgradeApiMemberRankDto
     * @param tenantId                租户id
     * @return com.medusa.gruul.payment.api.model.dto.PayResultDto
     */
    private PayResultDto upgradeApiMemberWechatPay(UpgradeApiMemberRankDto upgradeApiMemberRankDto, String tenantId) {
        PayRequestDto payRequestDto = new PayRequestDto();
       /* ShopConfigDto shopConfig = remoteMiniInfoService.getShopConfig(tenantId);
        if (shopConfig == null) {
            throw new ServiceException("商户配置不存在");
        }
        PayInfoVo payInfo = shopConfig.getPayInfo();
        if (payInfo == null) {
            throw new ServiceException("支付配置不存在");
        }*/
        //支付渠道 1-微信支付 2-环迅 3-随行 4-盛付通
        Integer payChannel = 1;
        Integer tradeType = 1;
        if (payChannel.equals(CommonConstants.NUMBER_ONE)) {
            tradeType = 1;
        } else if (payChannel.equals(CommonConstants.NUMBER_TWO)) {
            tradeType = 101;
        } else if (payChannel.equals(CommonConstants.NUMBER_THREE)) {
            tradeType = 201;
        } else if (payChannel.equals(CommonConstants.NUMBER_FOUR)) {
            tradeType = 301;
        } else {
            tradeType = 1;
        }
        String outTradeNo = upgradeApiMemberRankDto.getMemberNumber();
        CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
        String userId = "";
        String openId = "";
        if (curUserDto != null && curUserDto.getUserId() != null) {
            userId = curUserDto.getUserId();
            openId = curUserDto.getOpenId();
        }
        upgradeApiMemberRankDto.setTenantId(tenantId);
        upgradeApiMemberRankDto.setUserId(userId);
        String routekey = AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE;
        BigDecimal totalFee = upgradeApiMemberRankDto.getAvailableAmount();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            throw new ServiceException("数据异常");
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String teminalIp = IPUtils.getIpAddr(request);
        String feeType = "CNY";
        String timeoutExpress = "15m";
        String body = "会员升级";
        MemberCompletedVo memberCompletedVo = new MemberCompletedVo();
        memberCompletedVo.setUserRank(upgradeApiMemberRankDto.getRankCode())
                .setMNumber(upgradeApiMemberRankDto.getMemberNumber())
                .setType(3);
        String businessParams = JSON.toJSONString(memberCompletedVo);
        payRequestDto.setTenantId(tenantId);
        payRequestDto.setPayChannel(payChannel);
        payRequestDto.setTradeType(tradeType);
        payRequestDto.setOutTradeNo(outTradeNo);
        payRequestDto.setRouteKey(routekey);
        payRequestDto.setOpenId(openId);
        payRequestDto.setTotalFee(totalFee);
        payRequestDto.setTerminalIp(teminalIp);
        payRequestDto.setFeeType(feeType);
        payRequestDto.setTimeoutExpress(timeoutExpress);
        payRequestDto.setBody(body);
        payRequestDto.setBusinessParams(businessParams);
        PayResultDto payResultDto = remotePaymentService.payRequest(payRequestDto);
        log.debug(JSON.toJSONString(payResultDto));
        return payResultDto;
    }

    /**
     * 余额支付升级会员
     *
     * @param upgradeApiMemberRankDto com.medusa.gruul.account.model.dto.UpgradeApiMemberRankDto
     * @param tenantId                租户id
     */
    private void upgradeApiMemberBalancePay(UpgradeApiMemberRankDto upgradeApiMemberRankDto, String tenantId) {
        //会员升级
        int update = memberInfoMapper.upgradeApiMemberRank(upgradeApiMemberRankDto);
        if (update < 1) {
            throw new ServiceException("小程序端会员升级失败", SystemCode.DATA_UPDATE_FAILED.getCode());
        }
        CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
        String userId = "";
        if (curUserDto != null && curUserDto.getUserId() != null) {
            userId = curUserDto.getUserId();
        }
        BigDecimal amount1 = upgradeApiMemberRankDto.getUseAmount().subtract(upgradeApiMemberRankDto.getAvailableAmount());

        //增加返利
        MiniAccountExtends miniAccountExtends = miniAccountExtendsService.findByShopUserId(userId);
        //划款金额小于等于可用余额
        if (upgradeApiMemberRankDto.getAvailableAmount().compareTo(miniAccountExtends.getSupplyBonus()) <= 0) {
            BigDecimal amount = miniAccountExtends.getSupplyBonus().subtract(upgradeApiMemberRankDto.getAvailableAmount());
            int updateBonus = miniAccountMapper.updateBonus(tenantId, userId, amount);
            if (updateBonus < 1) {
                throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
            }
        } else {//划款金额大于可用余额
            int updateBonus = miniAccountMapper.updateBonus(tenantId, userId, new BigDecimal(0));
            if (updateBonus < 1) {
                throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
            }
            //获取返利设置，获取会员的返利设置
            String shopId = ShopContextHolder.getShopId();
            RebateSet rebateSet = remoteGoodsService.getRebateSet(tenantId, shopId);
            List<MemberInfo> memberInfoList = memberInfoMapper.selectList(new QueryWrapper<MemberInfo>().eq("state", 1).eq("tenant_id", tenantId).eq("user_id", userId));
            BigDecimal amount = new BigDecimal(0);
            //是会员
            if (memberInfoList != null && memberInfoList.size() > CommonConstants.NUMBER_ZERO) {
                if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ONE.toString())) {
                    amount = miniAccountExtends.getRebateBonus().
                            subtract(upgradeApiMemberRankDto
                                    .getAvailableAmount()
                                    .subtract(miniAccountExtends.getSupplyBonus()));
                } else {
                    throw new ServiceException("小程序端更新会员余额失败,划款金额大于用户可用余额", SystemCode.DATA_UPDATE_FAILED.getCode());
                }
            } else {//不是会员,是普通用户
                if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ZERO.toString())) {
                    amount = miniAccountExtends.getRebateBonus().subtract(upgradeApiMemberRankDto.getAvailableAmount().subtract(miniAccountExtends.getSupplyBonus()));
                } else {
                    throw new ServiceException("小程序端更新会员余额失败,划款金额大于用户可用余额", SystemCode.DATA_UPDATE_FAILED.getCode());
                }
            }

            int updateReBonus = miniAccountMapper.updateRebateBonus(tenantId, userId, amount);
            if (updateReBonus < CommonConstants.NUMBER_ONE) {
                throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
            }

        }

        //调取一下余额明细记录
        MemberInfo memberInfo = memberInfoMapper.selectOne(new QueryWrapper<MemberInfo>().eq("member_number", upgradeApiMemberRankDto.getMemberNumber()));
        MemberBalanceRecord memberBalanceRecord = new MemberBalanceRecord();
        memberBalanceRecord.setChangeType(CommonConstants.NUMBER_ONE)
                .setDealType(CommonConstants.NUMBER_ZERO)
                .setDetailName("会员升级")
                .setMemberInfoId(memberInfo.getId())
                .setShopUserId(Long.valueOf(miniAccountExtends.getShopUserId()))
                .setOrderId(Long.parseLong(MemberBalanceRecordServiceImpl.generateOrderRandomNo(tenantId, 7)))
                .setRemainingBalance(amount1)
                .setUseBalance(upgradeApiMemberRankDto.getAvailableAmount())
                .setOutOrderId(Long.parseLong(MemberInfoServiceImpl.generateRandomNo(tenantId, 7)))
                .setSource(CommonConstants.NUMBER_ONE);
        int inserts = memberBalanceRecordMapper.insert(memberBalanceRecord);
        if (inserts < CommonConstants.NUMBER_ONE) {
            throw new ServiceException("插入余额明细数据失败,外部订单号：" + memberBalanceRecord.getOutOrderId(), SystemCode.DATA_ADD_FAILED.getCode());
        }
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    /**
     * 更新到期时间，付费购买
     */
    private class Balance {
        private boolean myResult;
        private UpdateApiMemberExpireTimeDto updateApiMemberExpireTimeDto;
        private String tenantId;
        private PayResultDto payResultDto;

        public Balance(UpdateApiMemberExpireTimeDto updateApiMemberExpireTimeDto, String tenantId) {
            this.updateApiMemberExpireTimeDto = updateApiMemberExpireTimeDto;
            this.tenantId = tenantId;
        }

        boolean is() {
            return myResult;
        }

        public PayResultDto getPayResultDto() {
            return payResultDto;
        }

        public Balance invoke() {
            if (updateApiMemberExpireTimeDto.getPaymentType().equals(CommonConstants.NUMBER_ONE)) {
                //微信支付
                return wechatPay();
            } else if (updateApiMemberExpireTimeDto.getPaymentType().equals(CommonConstants.NUMBER_TWO)) {
                //余额支付
                balancePay();
            }
            myResult = false;
            return this;
        }

        /**
         * 微信支付
         *
         * @return com.medusa.gruul.account.service.impl.ApiMemberInfoServiceImpl.Balance
         */
        private Balance wechatPay() {
            PayRequestDto payRequestDto = new PayRequestDto();
            /*ShopConfigDto shopConfig = remoteMiniInfoService.getShopConfig(tenantId);
            if (shopConfig == null) {
                throw new ServiceException("商户配置不存在");
            }

            PayInfoVo payInfo = shopConfig.getPayInfo();
            if (payInfo == null) {
                throw new ServiceException("支付配置不存在");
            }*/
            //支付渠道 1-微信支付 2-环迅 3-随行 4-盛付通
            Integer payChannel =1;
            Integer tradeType = 1;
            if (payChannel.equals(CommonConstants.NUMBER_ONE)) {
                tradeType = CommonConstants.NUMBER_ONE;
            } else if (payChannel.equals(CommonConstants.NUMBER_TWO)) {
                tradeType = 101;
            } else if (payChannel.equals(CommonConstants.NUMBER_THREE)) {
                tradeType = 201;
            } else if (payChannel.equals(CommonConstants.NUMBER_FOUR)) {
                tradeType = 301;
            } else {
                tradeType = CommonConstants.NUMBER_ONE;
            }
            String outTradeNo = updateApiMemberExpireTimeDto.getMemberNumber();
            CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
            String userId = "";
            String openId = "";
            if (curUserDto != null && curUserDto.getUserId() != null) {
                userId = curUserDto.getUserId();
                openId = curUserDto.getOpenId();
            }
            updateApiMemberExpireTimeDto.setTenantId(tenantId);
            updateApiMemberExpireTimeDto.setUserId(userId);
            String routekey = AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE;
            BigDecimal totalFee = updateApiMemberExpireTimeDto.getAvailableAmount();
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                throw new ServiceException("服务异常");
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String teminalIp = IPUtils.getIpAddr(request);
            String feeType = "CNY";
            String timeoutExpress = "15m";
            String body = "会员续费";
            MemberCompletedVo memberCompletedVo = new MemberCompletedVo();
            memberCompletedVo.setUserRank(userId)
                    .setMNumber(updateApiMemberExpireTimeDto.getMemberNumber())
                    .setType(2)
                    .setDate(updateApiMemberExpireTimeDto.getDate());
            String businessParams = JSON.toJSONString(memberCompletedVo);
            payRequestDto.setTenantId(tenantId);
            payRequestDto.setPayChannel(payChannel);
            payRequestDto.setTradeType(tradeType);
            payRequestDto.setOutTradeNo(outTradeNo);
            payRequestDto.setRouteKey(routekey);
            payRequestDto.setOpenId(openId);
            payRequestDto.setTotalFee(totalFee);
            payRequestDto.setTerminalIp(teminalIp);
            payRequestDto.setFeeType(feeType);
            payRequestDto.setTimeoutExpress(timeoutExpress);
            payRequestDto.setBody(body);
            payRequestDto.setBusinessParams(businessParams);
            payResultDto = remotePaymentService.payRequest(payRequestDto);
            log.debug(JSON.toJSONString(payResultDto));
            myResult = true;
            return this;
        }

        /**
         * 余额支付
         */
        private void balancePay() {
            //会员续费
            //取时间
            Date date = DateUtil.parseDateTime(updateApiMemberExpireTimeDto.getMemberExpireTime());
            Calendar calendar = Calendar.getInstance();
            //需要将date数据转移到Calender对象中操作
            calendar.setTime(date);
            //把日期往后增加n天.正数往后推,负数往前移动
            calendar.add(Calendar.DATE, updateApiMemberExpireTimeDto.getDate().intValue());
            //这个时间就是日期往后推n天的结果
            date = calendar.getTime();
            updateApiMemberExpireTimeDto.setMemberExpireTime(DateUtil.formatDateTime(date));
            int update = memberInfoMapper.updateApiMemberExpireTime(updateApiMemberExpireTimeDto);
            if (update < 1) {
                throw new ServiceException("小程序端会员续费失败", SystemCode.DATA_UPDATE_FAILED.getCode());
            }
            CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
            String userId = "";
            if (curUserDto != null && curUserDto.getUserId() != null) {
                userId = curUserDto.getUserId();
            }
            BigDecimal amount1 = updateApiMemberExpireTimeDto.getUseAmount().subtract(updateApiMemberExpireTimeDto.getAvailableAmount());

            //增加返利
            MiniAccountExtends miniAccountExtends = miniAccountExtendsService.findByShopUserId(userId);
            if (updateApiMemberExpireTimeDto.getAvailableAmount().compareTo(miniAccountExtends.getSupplyBonus()) <= CommonConstants.NUMBER_ZERO) {
                //划款金额小于等于可用余额
                BigDecimal amount = miniAccountExtends.getSupplyBonus().subtract(updateApiMemberExpireTimeDto.getAvailableAmount());
                int updateBonus = miniAccountMapper.updateBonus(tenantId, userId, amount);
                if (updateBonus < CommonConstants.NUMBER_ONE) {
                    throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
                }
            } else {
                //划款金额大于可用余额
                int updateBonus = miniAccountMapper.updateBonus(tenantId, userId, new BigDecimal(CommonConstants.NUMBER_ZERO));
                if (updateBonus < CommonConstants.NUMBER_ONE) {
                    throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
                }
                //获取返利设置，获取会员的返利设置
                String shopId = ShopContextHolder.getShopId();
                RebateSet rebateSet = remoteGoodsService.getRebateSet(tenantId, shopId);
                List<MemberInfo> memberInfoList = memberInfoMapper.selectList(new QueryWrapper<MemberInfo>().eq("state", CommonConstants.NUMBER_ONE).eq("tenant_id", tenantId).eq("user_id", userId));
                BigDecimal amount = new BigDecimal(0);
                if (memberInfoList != null && memberInfoList.size() > 0) {//是会员
                    if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ONE.toString())) {
                        amount = miniAccountExtends.getRebateBonus().subtract(updateApiMemberExpireTimeDto.getAvailableAmount().subtract(miniAccountExtends.getSupplyBonus()));
                    } else {
                        throw new ServiceException("小程序端更新会员余额失败,划款金额大于用户可用余额", SystemCode.DATA_UPDATE_FAILED.getCode());
                    }
                } else {//不是会员,是普通用户
                    if (rebateSet != null && rebateSet.getBalanceUseCondition() != null && rebateSet.getBalanceUseCondition().contains(CommonConstants.NUMBER_ZERO.toString())) {
                        amount = miniAccountExtends.getRebateBonus().subtract(updateApiMemberExpireTimeDto.getAvailableAmount().subtract(miniAccountExtends.getSupplyBonus()));
                    } else {
                        throw new ServiceException("小程序端更新会员余额失败,划款金额大于用户可用余额", SystemCode.DATA_UPDATE_FAILED.getCode());
                    }
                }

                int updateReBonus = miniAccountMapper.updateRebateBonus(tenantId, userId, amount);
                if (updateReBonus < 1) {
                    throw new ServiceException("小程序端更新会员余额失败", SystemCode.DATA_UPDATE_FAILED.getCode());
                }

            }

            MemberInfo memberInfo = memberInfoMapper.selectOne(new QueryWrapper<MemberInfo>().eq("member_number", updateApiMemberExpireTimeDto.getMemberNumber()));
            //调取一下余额明细记录
            MemberBalanceRecord memberBalanceRecord = new MemberBalanceRecord();
            memberBalanceRecord.setChangeType(1)
                    .setDealType(0)
                    .setDetailName("会员续费")
                    .setMemberInfoId(memberInfo.getId())
                    .setShopUserId(Long.valueOf(miniAccountExtends.getShopUserId()))
                    .setOrderId(Long.parseLong(MemberBalanceRecordServiceImpl.generateOrderRandomNo(tenantId, 7)))
                    .setRemainingBalance(amount1)
                    .setUseBalance(updateApiMemberExpireTimeDto.getAvailableAmount())
                    .setOutOrderId(Long.parseLong(MemberInfoServiceImpl.generateRandomNo(tenantId, 7)))
                    .setSource(1);
            int inserts = memberBalanceRecordMapper.insert(memberBalanceRecord);
            if (inserts < 1) {
                throw new ServiceException("插入余额明细数据失败,外部订单号：" + memberBalanceRecord.getOutOrderId(), SystemCode.DATA_ADD_FAILED.getCode());
            }
        }
    }
}
